﻿using System;
using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using System.Text;
using GTA;

namespace PanelOverlay_Demo
{
    public class PanelOverlay_DemoScript : Script
    {
        private enum Status
        {
            Stopped = 0,
            Starting = 1,
            Started = 2
        }

        Status _status = Status.Stopped;

        GTAHookAdv.Overlay.PanelOverlay _panel_pictures;

        GTAHookAdv.Overlay.PictureBoxOverlay _pb_carCarrol;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_carEngine;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_carTank;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_wheelTopLeft;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_wheelTopRight;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_wheelBotLeft;
        GTAHookAdv.Overlay.PictureBoxOverlay _pb_wheelBotRight;

        public PanelOverlay_DemoScript()
        {

            this.GUID = new Guid("{6CEF8158-35C4-4887-B513-FE0203597870}");


            this.GeneralInfo = "PanelOverlay Demo\r\n\r\n";
            this.GeneralInfo += "Demonstrate how to use Containers to group several controls.\r\n\r\n";
            this.GeneralInfo += "Get in a car to display a panel composed of several controls:\r\n";
            this.GeneralInfo += "dynamic pictureboxes and a progressbar. This gives a great result !";

            this.Interval = 40;
            this.BindScriptCommand("Start", new ScriptCommandDelegate(OnStart));
            this.BindScriptCommand("Stop", new ScriptCommandDelegate(OnStop));
        }

        private void OnStop(Script sender, ObjectCollection Parameter)
        {
            GTAHookAdv.g_Game.DisplaySubTitle("Stopping Panel Overlay Demo", 7000, Color.Red);
            this.Tick -= On_Tick;
            //It is important to dispose Overlay components when it is not used anymore, as it consume Graphical memory and CPU time.
            if (_panel_pictures != null)
            {
                //Because you should use those controls somewhere else, childs are not automaticly disposed, you have to do it by your own :
                foreach (GTAHookAdv.Overlay.IControlOverlay currentchild in _panel_pictures.Childs)
                {
                    currentchild.Dispose();
                }

                //I repeat : childs are not disposed when we dispose a panel or any other control containing childs (see previous comment)
                _panel_pictures.Dispose();
                
            }
            _status = Status.Stopped;
        }

       

        private void OnStart(Script sender, ObjectCollection Parameter)
        {
            if (_status != Status.Stopped)
                return;
            BuildPanel();
            this.Tick += On_Tick;
            GTAHookAdv.g_Game.DisplaySubTitle("Get in a car to see the panel", 20000, Color.Green);
            _status = Status.Started;
            //Now look at On_Tick Method
        }

        private void BuildPanel()
        {
            _panel_pictures = new GTAHookAdv.Overlay.PanelOverlay(this);
            _panel_pictures.Visible = false; //childs will not be visible too, i'll change this when player get into a vehicle.
            _panel_pictures.BackColor = Color.Black;
            _panel_pictures.OpacityRange = GTAHookAdv.Overlay.OpacityRangeMode.OnlyThis; //Opacity will not be propagated to childs;
            _panel_pictures.Opacity = 40; //40% => 60% transparent

            //This is not the best choice to use Resources as it consume memory. But it garanties that picture are there (no FileNotFoundException possible)
            _pb_carCarrol = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_carrol);
            _pb_carEngine = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_engine);
            _pb_carTank = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_fuel);
            _pb_wheelBotLeft = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_wheel);
            _pb_wheelBotRight = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_wheel);
            _pb_wheelTopLeft = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_wheel);
            _pb_wheelTopRight = BuildPictureBox(global::PanelOverlay_Demo.Properties.Resources.car_wheel);

            //Here we are, this is the most important part of this demo:
            
            //carCarol is the big picture so i size the container (the panel) to its size
            _panel_pictures.Size = _pb_carCarrol.Image.Size;
            
            int margin = 20;
            //Lets say that all of this will be displayed at bottom right
            //Remember we always works on a 1920x1080 resolution, it will be scalled / translated if user have an other resolution such as 640x480 :p
            _panel_pictures.Location = new Point(
                1920 - margin - _panel_pictures.Width,
                1080 - margin - _panel_pictures.Height);

            //All controls will be a child, so their position is relative to the panel position.
            //We fix it once for all
            _pb_carCarrol.Location = new Point(0, 0); //same location as panel
            _pb_carEngine.Location = new Point(11, 4); //To be read at 11 pixels right of panel location , and 4 pixels bellow panel location
            _pb_carTank.Location = new Point(14, 180);
            _pb_wheelTopLeft.Location = new Point(4, 30);
            _pb_wheelTopRight.Location = new Point(115, 30);
            _pb_wheelBotLeft.Location = new Point(4, 189);
            _pb_wheelBotRight.Location = new Point(115, 189);

            //By default i'll paint wheels as darkGray
            _pb_wheelBotLeft.ForeColor = Color.DarkGray;
            _pb_wheelBotRight.ForeColor = Color.DarkGray;
            _pb_wheelTopLeft.ForeColor = Color.DarkGray;
            _pb_wheelTopRight.ForeColor = Color.DarkGray;

            //Important : keep in mind that adding childs act as adding layers in photoshop or Gimp. First child will be at back, last child will be in front.
            //In other word, the last child added should hide the first one
            //So this is important to choose witch child to add first !
            _panel_pictures.ChildAdd(_pb_wheelTopLeft);
            _panel_pictures.ChildAdd(_pb_wheelTopRight);
            _panel_pictures.ChildAdd(_pb_wheelBotRight);
            _panel_pictures.ChildAdd(_pb_wheelBotLeft);
            //Car will be drawn in front of wheels (see previous comment)
            _panel_pictures.ChildAdd(_pb_carCarrol);
            _panel_pictures.ChildAdd(_pb_carEngine);
            _panel_pictures.ChildAdd(_pb_carTank);

            

        }

        /// <summary>
        /// This method is not very interresting, it just garanty that all pictureboxes will have same properties
        /// </summary>
        private GTAHookAdv.Overlay.PictureBoxOverlay BuildPictureBox(Bitmap bitmap)
        {
            GTAHookAdv.Overlay.PictureBoxOverlay pictureCtrl = new GTAHookAdv.Overlay.PictureBoxOverlay(this);

            pictureCtrl.Size = bitmap.Size;
            pictureCtrl.Image = bitmap;
            pictureCtrl.Opacity = 100; //I can do it because _panel_pictures.OpacityRange == OpacityRangeMode.ThisOnly
            
            //set ForColor to white is useless as this this white by default:
            pictureCtrl.ForeColor = Color.White; //Means that by default we keep default color (see tick callback where we'll change it)
            return pictureCtrl;
        }

        private void On_Tick(object sender, EventArgs e)
        {
            if (_panel_pictures != null && !_panel_pictures.IsDisposed)
            {
                if (_status == Status.Started)
                {
                    bool isInVehicle = Player.Character.CurrentVehicle != null && Player.Character.CurrentVehicle.Exists();
                    
                    _panel_pictures.Visible = isInVehicle;

                    if (Player.Character.isGettingIntoAVehicle)
                        InitMaximumValues();

                    if (isInVehicle)
                    {
                        //This is out of demo, just we'll change pictures colors depending of car health
                        ColorDependOnHealth(ref _pb_carEngine, Player.Character.CurrentVehicle.EngineHealth, _maxEngineHealth);
                        ColorDependOnHealth(ref _pb_carTank, Player.Character.CurrentVehicle.PetrolTankHealth, _maxTankHealth);
                        ColorDependOnHealth(ref _pb_wheelTopLeft, GTA.VehicleWheel.FrontLeft);
                        ColorDependOnHealth(ref _pb_wheelTopRight, GTA.VehicleWheel.FrontRight);
                        ColorDependOnHealth(ref _pb_wheelBotLeft, GTA.VehicleWheel.RearLeft);
                        ColorDependOnHealth(ref _pb_wheelBotRight, GTA.VehicleWheel.RearRight);
                    }
                }
            }
        }

        
        private void ColorDependOnHealth(ref GTAHookAdv.Overlay.PictureBoxOverlay picturebox, VehicleWheel vehicleWheel)
        {
            if (Player.Character.CurrentVehicle.IsTireBurst(vehicleWheel))
            {
                picturebox.ForeColor = Color.Red;
                picturebox.Blink = true;
            }
            else
            {
                picturebox.ForeColor = Color.DarkGray;
                picturebox.Blink = false;
            }
        }

        /// <summary>
        /// Depending of car health, we change the picture color
        /// </summary>
        /// <param name="picturebox">target to be colored</param>
        /// <param name="currentHealth">what are we talking about? carrol, engine, fueltank</param>
        /// <param name="maxHealth">what is its max value</param>
        private void ColorDependOnHealth(ref GTAHookAdv.Overlay.PictureBoxOverlay picturebox,float currentHealth, float maxHealth)
        {
            //lets convert as percent
            float percent = currentHealth / maxHealth * 100f;

            if (percent >= 90)
            {
                picturebox.ForeColor = Color.White;
                picturebox.Blink = false;
                return;
            }
            if (percent >= 60)
            {
                picturebox.ForeColor = Color.Yellow;
                picturebox.Blink = false;
                return;
            }
            if (percent >= 30)
            {
                picturebox.ForeColor = Color.Orange;
                picturebox.Blink = false;
                return;
            }
            if (percent >= 1)
            {
                picturebox.ForeColor = Color.Red;
                picturebox.Blink = true;
                return;
            }
            picturebox.ForeColor = Color.Black; //Below 1% so it is dead :'(
            picturebox.Blink = true;
        }

        
        float _maxEngineHealth = 100f;
        float _maxTankHealth = 100f;
        /// <summary>
        /// Eatch kind of vehicle have its own maximum health properties. So lets get it
        /// </summary>
        private void InitMaximumValues()
        {
            //Vehcile class doesn't have a GetMaxHealth Field, so we have to do a small hack :
            //We build a clone of the vehicle, this clone will not be damaged as it is a fresh one.
            Vehicle vehi = GTA.World.CreateVehicle(Player.Character.CurrentVehicle.Model, new Vector3(310, 310, 310));
            //Now we know what are the Maximum heath values, let's use them :
            _maxEngineHealth = vehi.EngineHealth;
            _maxTankHealth = vehi.PetrolTankHealth;
            vehi.Delete();
            //Note : this hack is not really ressources consumming as the model and textures were allready into memory ;)
        }
    }
}
